package com.ncs.erp.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.ncsc.erp.model.SysCompany;
import com.ncsc.erp.model.SysCompanyAddr;
import com.ncsc.erp.model.SysCompanyNews;
import com.ncsc.erp.model.SysCompanySub;
import com.ncsc.erp.model.SysCurrency;
import com.ncsc.erp.model.SysOrg;
import com.ncsc.erp.model.SysTitleName;
import java.util.Iterator;

/**
 * Backing bean for SysCompany entities.
 * <p>
 * This class provides CRUD functionality for all SysCompany entities. It focuses
 * purely on Java EE 6 standards (e.g. <tt>&#64;ConversationScoped</tt> for
 * state management, <tt>PersistenceContext</tt> for persistence,
 * <tt>CriteriaBuilder</tt> for searches) rather than introducing a CRUD framework or
 * custom base class.
 */

@Named
@Stateful
@ConversationScoped
public class SysCompanyBean implements Serializable
{

   private static final long serialVersionUID = 1L;

   /*
    * Support creating and retrieving SysCompany entities
    */

   private Short id;

   public Short getId()
   {
      return this.id;
   }

   public void setId(Short id)
   {
      this.id = id;
   }

   private SysCompany sysCompany;

   public SysCompany getSysCompany()
   {
      return this.sysCompany;
   }

   @Inject
   private Conversation conversation;

   @PersistenceContext(type = PersistenceContextType.EXTENDED)
   private EntityManager entityManager;

   public String create()
   {

      this.conversation.begin();
      return "create?faces-redirect=true";
   }

   public void retrieve()
   {

      if (FacesContext.getCurrentInstance().isPostback())
      {
         return;
      }

      if (this.conversation.isTransient())
      {
         this.conversation.begin();
      }

      if (this.id == null)
      {
         this.sysCompany = this.example;
      }
      else
      {
         this.sysCompany = findById(getId());
      }
   }

   public SysCompany findById(Short id)
   {

      return this.entityManager.find(SysCompany.class, id);
   }

   /*
    * Support updating and deleting SysCompany entities
    */

   public String update()
   {
      this.conversation.end();

      try
      {
         if (this.id == null)
         {
            this.entityManager.persist(this.sysCompany);
            return "search?faces-redirect=true";
         }
         else
         {
            this.entityManager.merge(this.sysCompany);
            return "view?faces-redirect=true&id=" + this.sysCompany.getComNo();
         }
      }
      catch (Exception e)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
         return null;
      }
   }

   public String delete()
   {
      this.conversation.end();

      try
      {
         SysCompany deletableEntity = findById(getId());
         SysTitleName sysTitleName = deletableEntity.getSysTitleName();
         sysTitleName.getSysCompanies().remove(deletableEntity);
         deletableEntity.setSysTitleName(null);
         this.entityManager.merge(sysTitleName);
         SysCurrency sysCurrency = deletableEntity.getSysCurrency();
         sysCurrency.getSysCompanies().remove(deletableEntity);
         deletableEntity.setSysCurrency(null);
         this.entityManager.merge(sysCurrency);
         Iterator<SysCompanySub> iterSysCompanySubsForSubComNo = deletableEntity.getSysCompanySubsForSubComNo().iterator();
         for (; iterSysCompanySubsForSubComNo.hasNext();)
         {
            SysCompanySub nextInSysCompanySubsForSubComNo = iterSysCompanySubsForSubComNo.next();
            nextInSysCompanySubsForSubComNo.setSysCompanyBySubComNo(null);
            iterSysCompanySubsForSubComNo.remove();
            this.entityManager.merge(nextInSysCompanySubsForSubComNo);
         }
         Iterator<SysCompanySub> iterSysCompanySubsForComNo = deletableEntity.getSysCompanySubsForComNo().iterator();
         for (; iterSysCompanySubsForComNo.hasNext();)
         {
            SysCompanySub nextInSysCompanySubsForComNo = iterSysCompanySubsForComNo.next();
            nextInSysCompanySubsForComNo.setSysCompanyByComNo(null);
            iterSysCompanySubsForComNo.remove();
            this.entityManager.merge(nextInSysCompanySubsForComNo);
         }
         Iterator<SysOrg> iterSysOrgs = deletableEntity.getSysOrgs().iterator();
         for (; iterSysOrgs.hasNext();)
         {
            SysOrg nextInSysOrgs = iterSysOrgs.next();
            nextInSysOrgs.setSysCompany(null);
            iterSysOrgs.remove();
            this.entityManager.merge(nextInSysOrgs);
         }
         Iterator<SysCompanyNews> iterSysCompanyNewses = deletableEntity.getSysCompanyNewses().iterator();
         for (; iterSysCompanyNewses.hasNext();)
         {
            SysCompanyNews nextInSysCompanyNewses = iterSysCompanyNewses.next();
            nextInSysCompanyNewses.setSysCompany(null);
            iterSysCompanyNewses.remove();
            this.entityManager.merge(nextInSysCompanyNewses);
         }
         Iterator<SysCompanyAddr> iterSysCompanyAddrs = deletableEntity.getSysCompanyAddrs().iterator();
         for (; iterSysCompanyAddrs.hasNext();)
         {
            SysCompanyAddr nextInSysCompanyAddrs = iterSysCompanyAddrs.next();
            nextInSysCompanyAddrs.setSysCompany(null);
            iterSysCompanyAddrs.remove();
            this.entityManager.merge(nextInSysCompanyAddrs);
         }
         this.entityManager.remove(deletableEntity);
         this.entityManager.flush();
         return "search?faces-redirect=true";
      }
      catch (Exception e)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
         return null;
      }
   }

   /*
    * Support searching SysCompany entities with pagination
    */

   private int page;
   private long count;
   private List<SysCompany> pageItems;

   private SysCompany example = new SysCompany();

   public int getPage()
   {
      return this.page;
   }

   public void setPage(int page)
   {
      this.page = page;
   }

   public int getPageSize()
   {
      return 10;
   }

   public SysCompany getExample()
   {
      return this.example;
   }

   public void setExample(SysCompany example)
   {
      this.example = example;
   }

   public void search()
   {
      this.page = 0;
   }

   public void paginate()
   {

      CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

      // Populate this.count

      CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class);
      Root<SysCompany> root = countCriteria.from(SysCompany.class);
      countCriteria = countCriteria.select(builder.count(root)).where(
            getSearchPredicates(root));
      this.count = this.entityManager.createQuery(countCriteria)
            .getSingleResult();

      // Populate this.pageItems

      CriteriaQuery<SysCompany> criteria = builder.createQuery(SysCompany.class);
      root = criteria.from(SysCompany.class);
      TypedQuery<SysCompany> query = this.entityManager.createQuery(criteria
            .select(root).where(getSearchPredicates(root)));
      query.setFirstResult(this.page * getPageSize()).setMaxResults(
            getPageSize());
      this.pageItems = query.getResultList();
   }

   private Predicate[] getSearchPredicates(Root<SysCompany> root)
   {

      CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
      List<Predicate> predicatesList = new ArrayList<Predicate>();

      short comNo = this.example.getComNo();
      if (comNo != 0)
      {
         predicatesList.add(builder.equal(root.get("comNo"), comNo));
      }
      SysTitleName sysTitleName = this.example.getSysTitleName();
      if (sysTitleName != null)
      {
         predicatesList.add(builder.equal(root.get("sysTitleName"), sysTitleName));
      }
      SysCurrency sysCurrency = this.example.getSysCurrency();
      if (sysCurrency != null)
      {
         predicatesList.add(builder.equal(root.get("sysCurrency"), sysCurrency));
      }
      String comCode = this.example.getComCode();
      if (comCode != null && !"".equals(comCode))
      {
         predicatesList.add(builder.like(root.<String> get("comCode"), '%' + comCode + '%'));
      }
      String comName = this.example.getComName();
      if (comName != null && !"".equals(comName))
      {
         predicatesList.add(builder.like(root.<String> get("comName"), '%' + comName + '%'));
      }

      return predicatesList.toArray(new Predicate[predicatesList.size()]);
   }

   public List<SysCompany> getPageItems()
   {
      return this.pageItems;
   }

   public long getCount()
   {
      return this.count;
   }

   /*
    * Support listing and POSTing back SysCompany entities (e.g. from inside an
    * HtmlSelectOneMenu)
    */

   public List<SysCompany> getAll()
   {

      CriteriaQuery<SysCompany> criteria = this.entityManager
            .getCriteriaBuilder().createQuery(SysCompany.class);
      return this.entityManager.createQuery(
            criteria.select(criteria.from(SysCompany.class))).getResultList();
   }

   @Resource
   private SessionContext sessionContext;

   public Converter getConverter()
   {

      final SysCompanyBean ejbProxy = this.sessionContext.getBusinessObject(SysCompanyBean.class);

      return new Converter()
      {

         @Override
         public Object getAsObject(FacesContext context,
               UIComponent component, String value)
         {

            return ejbProxy.findById(Short.valueOf(value));
         }

         @Override
         public String getAsString(FacesContext context,
               UIComponent component, Object value)
         {

            if (value == null)
            {
               return "";
            }

            return String.valueOf(((SysCompany) value).getComNo());
         }
      };
   }

   /*
    * Support adding children to bidirectional, one-to-many tables
    */

   private SysCompany add = new SysCompany();

   public SysCompany getAdd()
   {
      return this.add;
   }

   public SysCompany getAdded()
   {
      SysCompany added = this.add;
      this.add = new SysCompany();
      return added;
   }
}